//
//  GZJsonValue.m
//  GZJsonValue
//
//  Created by GR on 2019/1/8.
//  Copyright © 2019 GR. All rights reserved.
//
//  为了确保json解析时，类型准确，和有一定的容错性，使得解析更安全。调用非常好的体现了数据的关系，同时避免了定义的大量的中间变量

#import "GZJsonValue.h"

@interface GZJsonValue ()

@property (nonatomic, strong) id object;

@end

@implementation GZJsonValue

+ (GZJsonValue *)valueWithObject:(id)objcet {
    GZJsonValue *value    = [[GZJsonValue alloc] init];
    value.object        = objcet;
    return value;
}

- (NSString *)string {
    if ([self.object isKindOfClass:[NSString class]]) { // 类型判断 + 容错
        return self.object; // 取值
    }
    
    if ([self.object isKindOfClass:[NSNumber class]]) {
        return [NSString stringWithFormat:@"%@", self.object];
    }
    
    return nil;
}

- (NSNumber *)number {
    if ([self.object isKindOfClass:[NSNumber class]]) {
        return self.object;
    }
    
    if ([self.object isKindOfClass:[NSString class]]) {
        NSString *string = (NSString *)self.object;
        
        if ([string isEqualToString:@"true"]) {
            return @YES;
        }
        else if ([string isEqualToString:@"false"]) {
            return @NO;
        }
        
        NSScanner *scanner = [NSScanner scannerWithString:string];
        double d = 0;
        [scanner scanDouble:&d];
        
        if (scanner.scanLocation != string.length) { // 字符串中不是纯数字
            return nil;
        }
        
        return [NSNumber numberWithDouble:d];
    }
    
    return nil;
}

- (NSDictionary *)dictionary {
    if ([self.object isKindOfClass:[NSDictionary class]]) {
        return self.object;
    }
    
    if ([self.object isKindOfClass:[NSString class]]) {
        NSString *jsonString = (NSString *)self.object;
        
        NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
        
        if (!data.length) {
            data = [[NSData alloc] initWithBase64EncodedString:jsonString options:NSDataBase64DecodingIgnoreUnknownCharacters];
        }
        
        if (!data.length) {
            return nil;
        }
        
        NSError *error = nil;
        id object = [NSJSONSerialization JSONObjectWithData:data
                                                    options:NSJSONReadingAllowFragments
                                                      error:&error];
        if (error || ![object isKindOfClass:[NSDictionary class]]) {
            NSLog(@"Serializate dictionary %@ occure error: %@", self.object, error);
            return nil;
        }
        
        return (NSDictionary *)object;
    }
    
    return nil;
}

- (NSArray *)array {
    if ([self.object isKindOfClass:[NSArray class]]) {
        return self.object;
    }
    
    if ([self.object isKindOfClass:[NSString class]]) {
        NSString *jsonString = (NSString *)self.object;
        
        NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
        
        if (!data.length) {
            data = [[NSData alloc] initWithBase64EncodedString:jsonString options:NSDataBase64DecodingIgnoreUnknownCharacters];
        }
        
        if (!data.length) {
            return nil;
        }
        
        NSError *error = nil;
        id object = [NSJSONSerialization JSONObjectWithData:data
                                                    options:NSJSONReadingAllowFragments
                                                      error:&error];
        if (error || ![object isKindOfClass:[NSArray class]]) {
            NSLog(@"Serializate array %@ occure error: %@", self.object, error);
            return nil;
        }
        
        return (NSArray *)object;
    }
    
    return nil;
}

- (GZJsonValue *)objectForKeyedSubscript:(NSString *)key {
    
    NSParameterAssert(key.length);
    
    if (!key.length) {
        return nil;
    }
    
    NSDictionary *dictionary = self.dictionary;
    if (!dictionary) {
        return nil;
    }
    
    GZJsonValue *value = [GZJsonValue valueWithObject:dictionary[key]];
    return value;
}

- (GZJsonValue *)objectAtIndexedSubscript:(NSUInteger)idx {
    
    NSParameterAssert(idx >= 0);
    
    if (idx < 0) {
        return nil;
    }
    
    NSArray *array = self.array;
    
    if (!array) {
        return nil;
    }
    
    if (idx >= array.count) {
        return nil;
    }
    
    GZJsonValue *value = [GZJsonValue valueWithObject:array[idx]];
    return value;
}
@end

@implementation GZJsonValue (NumericalValue)

- (BOOL)boolean {
    return self.number.boolValue;
}

- (NSUInteger)uintegerValue {
    return self.number.unsignedIntegerValue;
}

- (NSInteger)integerValue {
    return self.number.integerValue;
}

- (double)doubleValue {
    return self.number.doubleValue;
}

- (float)floatValue {
    return self.number.floatValue;
}

@end

@implementation GZJsonValue (Date)

- (NSDate *)date {
    double interval = self.doubleValue;
    
    if (interval > 1e12) {
        interval = interval / 1000;
    }
    
    return [NSDate dateWithTimeIntervalSince1970:interval];
}

- (NSDate *(^)(NSString *))dateFormat {
    return ^ NSDate* (NSString *format){

        NSString *string = self.string;
        
        if (!string.length || !format.length) {
            return nil;
        }
        
        NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
        fmt.calendar         = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
        fmt.dateFormat       = format;
        
        return [fmt dateFromString:string];
    };
}

@end
